Accessing root in-links of an object

Hi,

I'm brand new to DXL so please forgive me if I'm not using the right terms. I've been given the task of displaying an in-link trace (to the root object) for every object in a given module. I have written the following script.

string getTargets(Object obj, string finalString, int level)
{
    level++
        Link lnk
        for lnk in obj -> "*" do
        {
                Object newObj = target(lnk)
                finalString = getTargets(newObj, finalString, level)
        }
        level--
        string levelString=""
        int i
        for(i=0;i<level;i++)
        {
                levelString=levelString "..."
        }
        Module newMod = module(obj)
        string returnString = obj."Absolute Number" ""
        returnString = newMod."Prefix" returnString "\n" finalString
        returnString = levelString returnString 
        return returnString 
}
 
Module mod = current
Object obj
string filename = "Export.txt"
Stream out = write filename
for obj in mod do
{
        print getTargets(obj, "", 0)
        out << getTargets(obj, "", 0)
}
close out

 


This script works so long as I have every module along the path open, but if I don't, I get the error
-R-E- DXL: <Line:5> null Object parameter was passed into argument position 1

I assume this is because the object can't be loaded if the module is closed. How do I get around this? Or is there a better approach I should be taking? Thanks!

 


joeyvitoro - Thu Feb 02 10:29:29 EST 2012

Re: Accessing root in-links of an object
rain_bow - Thu Feb 02 13:00:38 EST 2012

In help file look for the following:
 

source 
Declaration 
string source({Link|LinkRef} l) 
ModName_ source({Link|LinkRef} l) 
Object source(Link l) 
Operation 
The first form returns the unqualified name of the module that is the source of l, which can be of type Link or LinkRef. 
 
The second form returns a reference to the module that is the source of l, which can be of type Link or LinkRef. 
 
The third form returns the source object of link l. 
 
Example 
Object o = current 
LinkRef lref 
ModName_ srcModRef 
for lref in o<-"*" do {
    srcModRef = source lref
    read(fullName(srcModRef), true)
}

Re: Accessing root in-links of an object
joeyvitoro - Thu Feb 02 13:28:43 EST 2012

rain_bow - Thu Feb 02 13:00:38 EST 2012

In help file look for the following:
 

source 
Declaration 
string source({Link|LinkRef} l) 
ModName_ source({Link|LinkRef} l) 
Object source(Link l) 
Operation 
The first form returns the unqualified name of the module that is the source of l, which can be of type Link or LinkRef. 
 
The second form returns a reference to the module that is the source of l, which can be of type Link or LinkRef. 
 
The third form returns the source object of link l. 
 
Example 
Object o = current 
LinkRef lref 
ModName_ srcModRef 
for lref in o<-"*" do {
    srcModRef = source lref
    read(fullName(srcModRef), true)
}

Thanks for the quick reply. That is the file I referenced for the code I have. I used the first form (though I needed target instead of source). Are you suggesting I use one of the other forms?

Re: Accessing root in-links of an object
SystemAdmin - Thu Feb 02 19:19:05 EST 2012

joeyvitoro - Thu Feb 02 13:28:43 EST 2012
Thanks for the quick reply. That is the file I referenced for the code I have. I used the first form (though I needed target instead of source). Are you suggesting I use one of the other forms?

The query was "I've been given the task of displaying an in-link trace (to the root object) for every object in a given module"

Why not use the DOORS "Analysis Wizard" feature to create a DXL Layout column that displays these multiple hop links back to the root (Module Menu: Analysis > Wizard).

This feature uses indenting to display the nested link relationships in one column, or there is an option to shown each link hop in separate columns (the one column option is recommended). It doesn't have a specific option to trace all the way back to the root, but all you need to do is set the "Specify Depth of Analysis" option to some high number so that you're confident that it's tracing all the way back to the root.

This would allow you to set up a DOORS module view that has a column for the UID, the Main column with the requirements text and a multiple hop trace column as described above, then print this View.

At the very least, you can view the DXL code that is auto generated for this feature which may you give you some ideas on the DXL code needed to do this.


Paul Miller
Melbourne, Australia

Re: Accessing root in-links of an object
joeyvitoro - Fri Feb 03 07:50:28 EST 2012

SystemAdmin - Thu Feb 02 19:19:05 EST 2012
The query was "I've been given the task of displaying an in-link trace (to the root object) for every object in a given module"

Why not use the DOORS "Analysis Wizard" feature to create a DXL Layout column that displays these multiple hop links back to the root (Module Menu: Analysis > Wizard).

This feature uses indenting to display the nested link relationships in one column, or there is an option to shown each link hop in separate columns (the one column option is recommended). It doesn't have a specific option to trace all the way back to the root, but all you need to do is set the "Specify Depth of Analysis" option to some high number so that you're confident that it's tracing all the way back to the root.

This would allow you to set up a DOORS module view that has a column for the UID, the Main column with the requirements text and a multiple hop trace column as described above, then print this View.

At the very least, you can view the DXL code that is auto generated for this feature which may you give you some ideas on the DXL code needed to do this.


Paul Miller
Melbourne, Australia

Paul,

That might be just what I need. Thanks! I've added the column as you suggested, but how do I view the DXL that was auto-generated?

Re: Accessing root in-links of an object
llandale - Fri Feb 03 09:21:18 EST 2012

Started this yesterday, finished this morning.

You cannot see an incoming "Link" unless the other module is open. Thus, in-link loops are preceded by that LinkRef loop used to open the source module. You don't need that here since you can always see an out "Link".

I see you say "in-link trace" but are looking at out-links "obj -> "*" do"

However, you cannot see the target Object unless that other module is open, so use some form of "read(target(lnk))" command. Might as well read the Link chapter in the DXL manual.

Its methodologically sound for recursive algorithms to start off with the trivial end-the-recursion-now constraints, in this case

  • if (null obj) return // nothing to do


"level" is modified in the function so you must "call by reference" using the ampersand &.

 

  • string getTargets(Object obj, string finalString, int & level)


You don't need to append the module "prefix", the "identifier()" perm gets the object identifier:
string returnString = identifier(obj) "\n" finalString

Use Buffers. We've all done it, but your function does too many concatenations and I see that the recursion concatenates the results. The resulting memory loss will be exponential. I'm guessing, but I suppose that a couple hundred objects visited will max out DOORS memory of a couple billion bytes.

I think you want one "out" line for each Object that is at the end of your chain.

I'm pretty sure you want to build up and output your your depth string, adding the ID of this object before checking it's subordinate links.

 

 

Buffer    g_bufResults = null
 
void    getTargets(Object obj, int level)
{
        if (null obj)                   return
 
        Link            lnk
        ModName_        mn
//      ModuleVersion   mv
        int             i
        Object          newObj
//ModuleVersion moduleVersion(ModName_)
//print identifier(obj) "\n"
        g_bufResults    += identifier(obj)
        g_bufResults    += "\n"
        for(i=0;i<level;i++)
        {
                g_bufResults += ".>>"
        }
 
        for lnk in obj -> "*" do
        {     mn = target(lnk)
                if (null mn)                    continue
                read(fullName(moduleVersion(mn)), false, true)
                newObj = target(lnk)
                getTargets(newObj, ++level)
        }
}
 
Module mod = current
Object obj
string filename = "c:\\Doors-Stuff\\Reports\\Export.txt"
Stream out = write filename
g_bufResults    = create()
for obj in mod do
{     setempty(g_bufResults)
        getTargets(obj, 0)
        out << tempStringOf(g_bufResults)
}
close out
delete(g_bufResults)
system("notepad.exe " filename)


You want to avoid naming variables the same spelling as functions. If there was a function with no parameters named "level", are you passing your variable or passing the function? Syntax highlighting editor helps here. (One more reason my variables have a short prefix, or start with Upper Case letters.)

-Louie

 

Re: Accessing root in-links of an object
joeyvitoro - Fri Feb 03 11:18:16 EST 2012

llandale - Fri Feb 03 09:21:18 EST 2012

Started this yesterday, finished this morning.

You cannot see an incoming "Link" unless the other module is open. Thus, in-link loops are preceded by that LinkRef loop used to open the source module. You don't need that here since you can always see an out "Link".

I see you say "in-link trace" but are looking at out-links "obj -> "*" do"

However, you cannot see the target Object unless that other module is open, so use some form of "read(target(lnk))" command. Might as well read the Link chapter in the DXL manual.

Its methodologically sound for recursive algorithms to start off with the trivial end-the-recursion-now constraints, in this case

  • if (null obj) return // nothing to do


"level" is modified in the function so you must "call by reference" using the ampersand &.

 

  • string getTargets(Object obj, string finalString, int & level)


You don't need to append the module "prefix", the "identifier()" perm gets the object identifier:
string returnString = identifier(obj) "\n" finalString

Use Buffers. We've all done it, but your function does too many concatenations and I see that the recursion concatenates the results. The resulting memory loss will be exponential. I'm guessing, but I suppose that a couple hundred objects visited will max out DOORS memory of a couple billion bytes.

I think you want one "out" line for each Object that is at the end of your chain.

I'm pretty sure you want to build up and output your your depth string, adding the ID of this object before checking it's subordinate links.

 

 

Buffer    g_bufResults = null
 
void    getTargets(Object obj, int level)
{
        if (null obj)                   return
 
        Link            lnk
        ModName_        mn
//      ModuleVersion   mv
        int             i
        Object          newObj
//ModuleVersion moduleVersion(ModName_)
//print identifier(obj) "\n"
        g_bufResults    += identifier(obj)
        g_bufResults    += "\n"
        for(i=0;i<level;i++)
        {
                g_bufResults += ".>>"
        }
 
        for lnk in obj -> "*" do
        {     mn = target(lnk)
                if (null mn)                    continue
                read(fullName(moduleVersion(mn)), false, true)
                newObj = target(lnk)
                getTargets(newObj, ++level)
        }
}
 
Module mod = current
Object obj
string filename = "c:\\Doors-Stuff\\Reports\\Export.txt"
Stream out = write filename
g_bufResults    = create()
for obj in mod do
{     setempty(g_bufResults)
        getTargets(obj, 0)
        out << tempStringOf(g_bufResults)
}
close out
delete(g_bufResults)
system("notepad.exe " filename)


You want to avoid naming variables the same spelling as functions. If there was a function with no parameters named "level", are you passing your variable or passing the function? Syntax highlighting editor helps here. (One more reason my variables have a short prefix, or start with Upper Case letters.)

-Louie

 

That was perfect, thank you! I appreciate the advice on better and more efficient coding practices!

Re: Accessing root in-links of an object
SystemAdmin - Fri Feb 03 16:34:58 EST 2012

joeyvitoro - Fri Feb 03 07:50:28 EST 2012
Paul,

That might be just what I need. Thanks! I've added the column as you suggested, but how do I view the DXL that was auto-generated?

....how do I view the DXL that was auto-generated?...

Hover your mouse over the title cell of the column that was created by the Analysis Wizard

RH mouse click, select Properties - the Layout DXL radio button option should already be selected

Click the Browse button

Click the Current button


Paul Miller
Melbourne, Australia